/*
* Copyright (c) 2016 . All Rights Reserved.
*/
package com.cgmnx.admin.web.converter.vm;

import com.cgmnx.admin.common.enums.ValidEnumType;
import com.cgmnx.admin.common.util.DateUtil;
import com.cgmnx.admin.dao.entity.rbac.ResourceEntity;
import com.cgmnx.admin.dao.entity.rbac.ResourceTree;
import com.cgmnx.admin.model.enums.rbac.ResourceType;
import com.cgmnx.admin.web.converter.Convert;
import com.cgmnx.admin.web.model.vm.ResourceVm;
import com.google.common.base.Function;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author: created  Date: 16/12/21 Time: 下午4:22
 * @version: 1.0
 */
@Component
public class ResourceVmConverter implements Convert<ResourceEntity, ResourceVm> {

    private static final Integer MAIN_URI_FLAG = 0;

    private static List<ResourceTree> getChildren(Integer parentId,
                                                  Map<Integer, ResourceEntity> idEntity,
                                                  Map<Integer, Collection<Integer>> parentIds) {

        if (CollectionUtils.isEmpty(parentIds.get(parentId))) {
            return Collections.emptyList();
        }

        List<ResourceTree> uriTreeVos = Lists.newArrayList();

        for (Integer id : parentIds.get(parentId)) {

            uriTreeVos.add(getUriTreeVo(idEntity, parentIds, id));

        }

        return uriTreeVos;
    }

    private static ResourceTree getUriTreeVo(Map<Integer, ResourceEntity> idEntity, Map<Integer, Collection<Integer>> parentIds, Integer id) {

        ResourceTree vo = entity2Tree(idEntity.get(id));

        vo.setChildren(getChildren(id, idEntity, parentIds));

        return vo;
    }

    private static ResourceTree entity2Tree(ResourceEntity entity) {
        ResourceTree vo = new ResourceTree();
        vo.setId(entity.getId());
        vo.setName(entity.getName());
        vo.setUri(entity.getUri());
        return vo;
    }

    public List<ResourceTree> entities2Tree(List<ResourceEntity> from) {
        if (from == null) {
            return Collections.emptyList();
        }

        Map<Integer, ResourceEntity> idEntity = Maps.uniqueIndex(from, new Function<ResourceEntity, Integer>() {
            @Override
            public Integer apply(ResourceEntity input) {
                return input.getId();
            }
        });

        Multimap<Integer, Integer> parentIdWithIds = ArrayListMultimap.create();

        for (ResourceEntity vo : from) {
            parentIdWithIds.put(vo.getParentId(), vo.getId());
        }

        Map<Integer, Collection<Integer>> parentIds = parentIdWithIds.asMap();

        return getChildren(MAIN_URI_FLAG, idEntity, parentIds);
    }

    @Override
    public ResourceVm convert(ResourceEntity t) {

        if (t == null) {
            return null;
        }

        ResourceVm vm = new ResourceVm();
        vm.setId(t.getId());
        vm.setName(t.getName());
        vm.setDescription(t.getDescription());
        vm.setIcon(t.getIcon());
        vm.setParentId(t.getParentId());
        vm.setParentName(t.getParentName());
        vm.setUri(t.getUri());
        vm.setTreeCode(t.getTreeCode());
        vm.setSort(t.getSort());
        vm.setNodeCount(t.getNodeCount());
        vm.setIsParent(t.getNodeCount() > 0);
        ResourceType showType = t.getShowType();
        if (showType != null) {
            vm.setShowTypeCode(showType.getCode());
            vm.setShowTypeText(showType.getDesc());
        }

        ValidEnumType validStatus = t.getValidStatus();
        if (validStatus != null) {
            vm.setValidStatusCode(validStatus.getCode());
            vm.setValidStatusText(validStatus.getText());
        }
        vm.setUpdateUser(t.getUpdateUser());
        vm.setCreateUser(t.getCreateUser());
        vm.setCreateTime(DateUtil.formatDatetime(t.getCreateTime()));
        vm.setUpdateTime(DateUtil.formatDatetime(t.getUpdateTime()));
        return vm;
    }

    @Override
    public List<ResourceVm> convert(List<ResourceEntity> t) {

        if (CollectionUtils.isEmpty(t)) {
            return Collections.emptyList();
        }

        return FluentIterable.from(t).transform(new Function<ResourceEntity, ResourceVm>() {

            @Override
            public ResourceVm apply(ResourceEntity input) {

                if (input == null) {
                    return null;
                }

                return convert(input);
            }
        }).toList();
    }
}